#ifndef __ES_ENCODE_H__
#define __ES_ENCODE_H__


#include "stm_std_lib.h"
#include "es_spi.h"
#include "es_usart.h"

//extern CBoard Board;



#define BUFFER_SIZE 127


	typedef void (*Package)(u8*, u8);

enum BufferType{SPI, UART};
	





//包通知接口
class InterfacePackageNotify{
	public:
	virtual void SPINewPacketHandler(u8* buff, u8 size)=0;
	virtual void UARTNewPacketHandler(u8* buff, u8 size)=0;
};




class Buffer
{
public:
	u8 count;
	u8 size;
	u8 buffer[BUFFER_SIZE];
  BufferType port;
	InterfacePackageNotify* newPackage;		//接口指针

	void init(InterfacePackageNotify* packNofify, BufferType t)
	{
		//指针函数
		newPackage = packNofify;
		count =0;
		port = t;
	}
	
 void insert(u8 data)
	{
		//第一个包， 或者错误
		if(data>>7 == 0)
		{
			//重设数据
			count=0;
			size = data;
		}
		else
		{
			//写进buffer
			buffer[count%127] = data;
					count++;
			//通知有新数据包
			if(count==size){
				switch(port)
				{
					case SPI:
						newPackage->SPINewPacketHandler(buffer,size);
						break;
					case UART:
						newPackage->UARTNewPacketHandler(buffer,size);
						break;
				}
				//newPackage(buffer, size);
			}
		
		}
	}
};


class es_SerialPack:public InterfacePackageNotify
{
	//有新数据来时call NewData, 然后NewData会插入到Buffer对象，  Buffer对象发现数据够了时，
  //	会call Buffer.init时传入的指针函数, 这个函数应该是NewPacketHandler， 然后解码，再call 
	//SPIPackageReady， 这个指针函数是es_SerialPack.init() 时传入的
	

	
private:
	Buffer SPIReadBuffer;
	Buffer UARTReadBuffer;

	u8* SPIBuffer;
	u8 SPIBufferSize;

	u8* UARTBuffer;
	u8 UARTBufferSize;

	Package SPIPackageReady;
	Package UARTPackageReady;

	CSPI* pSpi;
	CUsart* pUsart;

	//when SPI coded data is ready, decode it, and notice subscriber
	virtual void SPINewPacketHandler(u8* buff, u8 size)
	{
		SPIBufferSize = getDecodeBufferLen(size);
		decode(buff, size, SPIBuffer);
		SPIPackageReady(SPIBuffer, SPIBufferSize);
	}
	//when UART coded data is ready, decode it, and notice subscriber
  virtual void UARTNewPacketHandler(u8* buff, u8 size)
	{
		UARTBufferSize = getDecodeBufferLen(size);
		decode(buff, size, UARTBuffer);
		UARTPackageReady(UARTBuffer, UARTBufferSize);
	}
		//由原字节长度计算编码后缓冲区长度
	int getEncodeBufferLen(int byteLen) {
		return byteLen * 8 / 7 + ((byteLen * 8) % 7 > 0 ? 1 : 0);
	}

	//由编码包长度计算解码后缓冲区长度
	int getDecodeBufferLen(int byteLen) {
		return byteLen * 7 / 8;// + ((byteLen * 7) % 8 > 0 ? 1 : 0);
	}


	//编码 data编码后写入encodeBuffer中
	void encode(u8* data, int len, u8* encodeBuffer) {
		//编码缓存全部置初值为 1000 0000b
		int blen = getEncodeBufferLen(len);
		for (int i = 0; i < blen; i++) {
			encodeBuffer[i] = 0x80;
		}

		//编码算法
		int pointer = 0;
		for (int i = 0; i < len; i++) {
			//byte编号
			int n = (i % 7) + 1;

			u8 massH = (0xff >> n) << n;	//高位掩码
			u8 massL = massH ^ 0xff;		//低位掩码


			//计算高位
			u8 H = (u8)(((data[i] & massH) & 0xff) >> n);

			//计算低位
			u8 L = (u8)(((data[i] & massL) & 0xff) << (7 - n));



			//写入buffer
			//高位
			encodeBuffer[pointer] = encodeBuffer[pointer] | H;
			pointer++;

			//低位				
			encodeBuffer[pointer] = encodeBuffer[pointer] | L;

			//写完第7byte后，进入下一轮循环
			if (n == 7)pointer++;
		}
	}



	//解码 encodeBuffer解码后写入data
	void decode(u8* encodeBuffer, int len, u8* data) {
		//首先将编码缓存所有最高位置0 (协议规定传输时最高位为1)
		for (int i = 0; i < len; i++) {
			encodeBuffer[i] = encodeBuffer[i] & 0x7f;
		}


		//原包长度
		int dataLen = getDecodeBufferLen(len);

		int pointer = 0;
		for (int i = 0; i < dataLen; i++) {
			//byte编号
			int n = (i % 7) + 1;


			//获取数据包所在载体
			u8 k1 = encodeBuffer[pointer++];
			u8 k2 = encodeBuffer[pointer];
			if (n % 7 == 0)pointer++;		//每7个数据包一次循环


			u8 massH = 0xff >> n;	//高位掩码
			u8 massL = (u8)(((massH ^ 0xff) & 0xff) >> 1);		//低位掩码


			u8 H = (u8)(((k1&massH) & 0xff) << n);
			u8 L = (u8)(((k2&massL) & 0xff) >> (7 - n));

			//还原		
			data[i] = H | L;
		}
	}
public:
	

	//new data from SPI bus 新数据， SPI新数据中断call这个函数
	void SPINewData(u8 val)
	{
		SPIReadBuffer.insert(val);
	}
	//new data from usart bus 新数据， UART有新数据call这个函数
	void UARTNewData(u8 val)
	{
		UARTReadBuffer.insert(val);
	}

	//初始化
	//传入处理SPI和UART数据解码后的指针函数
	void Init(Package SPIPackageReady, Package UARTPackageReady, CSPI* spi, CUsart* usart)
	{
		//init buffers for incoming data
		SPIBuffer = new u8[BUFFER_SIZE];
		UARTBuffer = new u8[BUFFER_SIZE];
		//
 		this->SPIPackageReady = SPIPackageReady;
 		this->UARTPackageReady = UARTPackageReady;
		
		SPIReadBuffer.init(this, SPI); 
		UARTReadBuffer.init(this, UART);

		this->pSpi = spi;
		this->pUsart = usart;

		
	}
	void Depose()
	{
		delete[] SPIBuffer;
		delete[] UARTBuffer;
	}
	
	//发送数据包
	void UARTWriteData(u8* buff, u8 size)
	{
		u8 len = getEncodeBufferLen(size);
		u8* buffer = new u8[len];
		encode(buff, size, buffer);
		pUsart->Write(len);
		pUsart->Write(buffer, len);
		delete[] buffer;
	}
	//发送数据包
	void SPIWriteData(u8* buff, u8 size)
	{
		u8 len = getEncodeBufferLen(size);
		u8* buffer = new u8[len];
		encode(buff, size, buffer);
		
		//SPI发送（同时会接收，未处理）
		u8* recvBuf=new u8[len];
		pSpi->WriteRead(len);
		pSpi->WriteRead(buffer,recvBuf,len);
		delete[] buffer;
		delete[] recvBuf;
	}
};

#endif
